package finance

class HistoricalFitController {
    def correlationService
    def polynomialFitService
    def historicalQueryService
    def relativeErrorService
    def descriptiveStatisticsService
    def noiseService
    def fieldname = "Close"
    
    def index = { 
        
        if(params.select1 != null) {
            def map = historicalQueryService.pairedValuesMap(params.select1, 
            params.select2, fieldname)
            def responseMap = [:]
            def data1 = map["data1"]
            def data2 = map["data2"]
            responseMap["corrParams"] = correlationService.correlate(data1, data2)
            responseMap["polynomial"] = polynomialFitService.fit(params.power,
            data1[0..<200], data2[0..<200])
            
            responseMap["fitData"] = 
            polynomialFitService.eval( data1, responseMap["polynomial"] )
            
            def descStats = errorStats( data2, 
            responseMap["fitData"] )
            responseMap["stats"] = descStats
            
            def data = [:]
            
            for( i in 0..<data1.size())
            data[data1[i]] = data2[i]
            
            responseMap["data"] = data
            
            
            return responseMap
        }
    }
    
    def single = {
        if(params.select1 != null) {
            def data = historicalQueryService.queryVals(params.select1, 
            fieldname)
            def responseMap = [:]
            responseMap["polynomial"] = polynomialFitService.fit(params.power,
            0..<200, data[0..<200])
            
            responseMap["fitData"] = 
            polynomialFitService.eval( 0..data.size(), 
            responseMap["polynomial"] )
            
            def descStats = errorStats( data, 
            responseMap["fitData"] )
            responseMap["stats"] = descStats
            
            def dataMap = [:]
            
            for( i in 0..<data.size())
            dataMap[i + 1] = data[i]
            
            responseMap["data"] = dataMap
            
            return responseMap
        }
    }
    
    def errorStats(data, fittedData) {
        def statsList = []
        
        for(i in 0 .. 5) {
            def noisyData = noiseService.add( fittedData.values().asList(),
            0.01  * 2 ** i) 
            def error = relativeErrorService.error( data, 
            noisyData)
            statsList << descriptiveStatisticsService.stats(error)
        }
        
        return statsList
    }
}
